var ideon = {
	module: function() {
		var modules = {};
		
		return function(name, actions) {
			if(modules[name]) {
				return modules[name];
			}
			
			return modules[name] = {
				Model: {},
				Collection: {},
				View: {},
				Router: {},
			};
		}
	}(),
};


(function(Base){		
	// UTILS
	function defaultErrorHandler(model, error) {
		var errorJSON = jQuery.parseJSON(error.responseText);
		var errorView = new Base.View.BaseErrorView({
			model: model,
			error: errorJSON,
		});
		errorView.render();
	}
	
	// MODELS
	Base.Model.BaseModel = Backbone.Model.extend({
		initialize: function() {
			console.log("Base Model");
			this.bind("error", defaultErrorHandler);
		},
	});
	
	Base.Model.Focus = Base.Model.BaseModel.extend({});
	Base.Model.Information = Base.Model.BaseModel.extend({});
	Base.Model.InfoUnit = Base.Model.BaseModel.extend({});
	Base.Model.User = Base.Model.BaseModel.extend({});
	
	// COLLECTIONS
	Base.Collection.BaseCollection = Backbone.Collection.extend({
		initialize: function() {
			this.bind("error", defaultErrorHandler);
		},
	});
	
	Base.Collection.Paginated = Base.Collection.BaseCollection.extend({
		DEFAULT_LIMIT: 10,
		DEFAULT_SORTBY: 'name_asc',
		
		initialize: function(models, options) {
			Base.Collection.BaseCollection.prototype.initialize.call(this);
			
			options || (options = {});
			if(options.paginated) this.paginated = true;
			else this.paginated = false;
			
			if(this.paginated) {
				this.offset = options.offset || 0;
				this.limit  = options.limit || this.DEFAULT_LIMIT;
				this.sortBy = options.sortBy || this.DEFAULT_SORTBY; 
				this.bind("add", this.paginationAdd, this);
				this.bind("remove", this.paginationRemove, this);
			}
		},
		
		paginationAdd: function() {
			this.total++;
		},
		
		paginationRemove: function() {
			this.total--;
		},
		
		pageInfo: function() {
			var info = {
			  total: this.total,
			  page: this.page,
			  perPage: this.perPage,
			  pages: Math.ceil(this.total / this.perPage),
			  prev: false,
			  next: false
			};

			var max = Math.min(this.total, this.page * this.perPage);

			if (this.total == this.pages * this.perPage) {
			  max = this.total;
			}

			info.range = [];

			for(var i = 1 ; i <= info.pages; i++) {
				info.range.push(i);
			}

			if (this.page > 1) {
			  info.prev = this.page - 1;
			}

			if (this.page < info.pages) {
			  info.next = this.page + 1;
			}

			console.log("Total: " + info.total);
			console.log("Page: " + info.page);
			console.log("Pages: " + info.pages);
			console.log("Range: " + info.range);
			return info;
		},
		
		fetch: function(options) {
			console.log("Paginated collection -> fetch -> is paginated: " + this.paginated)
			options || (options = {});
			
			if(this.paginated) {
				var iDisplayStart =  encodeURIComponent(this.offset);
				var iDisplayLength = encodeURIComponent(this.limit);	
				var sort_by =  encodeURIComponent(this.sortBy);
				options.data = {iDisplayStart: iDisplayStart, iDisplayLength: iDisplayLength, sort_by: sort_by};		
				console.log(options.data);
			}
			
			return Backbone.Collection.prototype.fetch.call(this, options);
		},

		parse: function(resp) {
			console.log("parse");
			if(this.paginated) {
				this.perPage = resp.iDisplayLength;
				this.total = resp.iTotalRecords;
				this.page = resp.start != 0 ? resp.start : 1;
				return resp.rows;
			}
			
			return resp;
			
		},	
	});
	
	// VIEWS
	// This view has to be used with the List view.	
	Base.View.Item = Backbone.View.extend({
		//tagName: "li",
		
		render: function() {
			$(this.el).html(this.template({data: this.model}));
			this.hideDetail();
			return this;
		},
		
		hideDetail: function() {
			this.$(".detail").hide();
		},
		
		showDetail: function() {
			this.$(".detail").slideToggle();
		}
		
	});
	
	Base.View.ListView = Backbone.View.extend({
		_itemView:	Base.View.Item,
		
		//template: _.template($("#list-template").html()),
		
		events: {
			"click a.page":		"changePage",
		},
			
		initialize: function() {
			this.collection.bind("reset", this.render, this);
		},
		
		render: function() {
			this.renderList();
			
			return this;
		},
		
		renderList: function() {
			// Build pagination and the body template
			$(this.el).html(this.template({pagination: this.collection.pageInfo()}));
			var self = this;
			
			// Build the list
			var $list = this.$(".list");
			
			this.collection.each(function(item){
				var itemView = new self._itemView({
					model:	item,
					collection: self.collection
				});
				$list.append(itemView.render().el);
			});
			console.log(this.collection.pageInfo());
		},
		
		changePage: function(e) {
			console.log("Change page");
			e.preventDefault();
			var page = $(e.currentTarget).data("id") ? $(e.currentTarget).data("id") : 1;
			var start = (page-1) * this.collection.limit;
			this.collection.offset = start;
			this.collection.fetch();
			
			//router.navigate("#page"+page, true);
		}
	});
	
	Base.View.Editor = Backbone.View.extend({ // TODO Sumbit form with unique save method. Serialize form into a json object!
		tagName: "div",
		className: "editor",
		
		events: {
				"click button.close":			"close",
				"click button[name=save]":		"save",
				"click button[name=cancel]":	"cancel",
				"submit form":					"stopSubmit",
		},
			
		initialize: function() {
			_.bindAll(this, 'successHandler',
							'errorHandler',
							'save',
							'stopSubmit',
							'cancel',
							'close');
		},
		
		stopSubmit: function(e) {
			// Clear all errors class
			e.preventDefault(); 
		},
		
		close: function() {
				console.log("EditorView-> closing");
				$(this.el).hide();
				$(this.el).remove();
		},

		cancel: function() {
			console.log("EditorView -> cancel");
			this.close();
		},
		
		successHandler: function(model, response) {
			this.close();
		},

		errorHandler: function(model, response) {
			console.log("EditorView -> errorHandler");
			// Clean old errors
			$(".error").removeClass("error");
			// Clean old help errors
			$(".help-inline").html("");
			var rJson = jQuery.parseJSON(response.responseText);
			console.log(rJson);
			var errors = this.$(".errors").empty();
			for(var key in rJson.errors) {
				if(key.indexOf(".") != -1) {
					var $inputField =  $("#" + key.replace(".", "_"));
					var error = "Error: The field " + key + " is " + rJson.errors[key];
					console.log(error);
					if($inputField) {
						//var $erroField = $("<span></span>", {html: error}).addClass("error");
						//$inputField.after().remove();
						//$inputField.after($erroField);
						$inputField.parent().parent().addClass("error");
						$(".help-inline", $inputField.parent()).html(error);
					}
					else errors.append(error);
				} else {
					// TODO
				}	
			}
		},
	});
	
	Base.View.ModalEditor = Backbone.View.extend({
		tagName:		"div",
		className:		"modal hide fade",

		events: {
			"click button.close":			"close",
			"click button[name=save]":		"save",
			"click button[name=cancel]":	"cancel",
			"submit form":					"stopSubmit",
		},

		initialize: function() {
			console.log("ModalEditor -> initialize");
			
			$(this.el).attr("id", this.model.isNew() ? "new" : "edit-" + this.model.get("id"));
			_.bindAll(this, 'successHandler',
							'errorHandler',
							'save',
							'stopSubmit',
							'cancel',
							'close');
		},
		
		render: function() {
			this.renderContain();
			$(this.el).modal({"show": true, "data-backdrop": true, "backdrop": true,});
			return this;
		},
		
		renderContain: function() {
			$(this.el).html(this.template( {model: this.model} ));
		},
		
		save: function() {
			console.log("FocusEditor -> save");
			var title = $("#focus_title", this.el).val();
			var description = $("#focus_description", this.el).val();
			if(!this.model.isNew()) {
				console.log("Editando");
				this.model.save( {title: title, description: description}, {success: this.successHandler, error: this.errorHandler} );
			} else {
				console.log("Creando");
				this.collection.create( {title: title, description: description}, {success: this.successHandler, error: this.errorHandler} );
			}
		},
		
		stopSubmit: function(e) {
			// Clear all errors class
			e.preventDefault(); 
		},
		
		close: function() {
			console.log("ModalForm-> closing");
			$(this.el).modal('hide');
			$(this.el).remove();	
		},

		cancel: function() {
			console.log("ModalForm -> cancel");
			this.close();
		},
		
		successHandler: function(model, response) {
			console.log("ModalForm -> successHandler");
			this.close();
		},

		errorHandler: function(model, response) {
			console.log("EditorView -> errorHandler");
			// Clean old errors
			$(".error").removeClass("error");
			// Clean old help errors
			$(".help-inline").html("");
			var rJson = jQuery.parseJSON(response.responseText);
			console.log(rJson);
			var errors = this.$(".errors").empty();
			for(var key in rJson.errors) {
				if(key.indexOf(".") != -1) {
					var $inputField =  $("#" + key.replace(".", "_"));
					var error = "Error: The field " + key + " is " + rJson.errors[key];
					console.log(error);
					if($inputField) {
						//var $erroField = $("<span></span>", {html: error}).addClass("error");
						//$inputField.after().remove();
						//$inputField.after($erroField);
						$inputField.parent().parent().addClass("error");
						$(".help-inline", $inputField.parent()).html(error);
					}
					else errors.append(error);
				} else {
					// TODO
				}	
			}
		},
	});
			
	Base.View.BaseErrorView = Backbone.View.extend({
		el: $("#error"),
		tagName: "div",
		initialize: function(options) {
			this.error = options.error;
		},
		
		render: function(){
			console.log("ErrorView");
			console.log(this.error);
			var message = this.error.message;
			
			var $message = $("<p></p>", {html: this.error.message});
			this.el.html($message);
			return this;
		},
	});
	
	Base.View.Loading = Backbone.View.extend({
		
		initialize: function() {
		},
		
		render: function() {
			$(this.el).hide();
			$(this.el).html("Please wait! Loading data....");
			return this;
		},
		
		show: function() {
			$(this.el).show();
		},
		
		hide: function() {
			$(this.el).hide();
		}
	});
	
	Base.View.App = Backbone.View.extend({
		el: "#content",
	});
	// ROUTERS
})(ideon.module("base"));
